package com.huawei.boss.http;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.SimpleHttpConnectionManager;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Http请求工具
 * @author c00170351
 */
public class HttpRequestProxy {
    private static final Logger LOG = LoggerFactory.getLogger(HttpRequestProxy.class);
    //超时间隔 TODO
    private static final int CONNECT_TIMEOUT = 60000;
    private static final String CRLF = System.getProperty("line.separator");
    //让connectionmanager管理httpclientconnection时是否关闭连接
    private static final boolean ALWAYS_CLOSE = true;
    private static final String DEFAULT_ENCODING = "UTF-8";
    private String url;
    //返回数据编码格式
    private String encoding = DEFAULT_ENCODING;
    private Map<String, String> header;
    //请求数据
    private Map<String, String> postData;
    //soap请求数据
    private String soapData;

    private final HttpClient httpClient = new HttpClient(new SimpleHttpConnectionManager(ALWAYS_CLOSE));

    public String doRequest() throws Exception {
        
        Header[] headers = buildHeaders();
        
        //TODO 下面几段分支代码比较恶心，代码重复比较多，需要重构
        //POST
        if (soapData != null) {
            PostMethod request = new PostMethod(url);
            // 增加cookie内容的容错处理(兼容性)。
            request.getParams().setParameter("http.protocol.cookie-policy", CookiePolicy.BROWSER_COMPATIBILITY);
            
            //String contentType = "application/soap+xml; charset=" + encoding + "; type=\"text/xml\"";
            if (headers != null) {
                for (int i = 0; i < headers.length; i++) {
                    request.setRequestHeader(headers[i]);
                }
            }

            byte[] b = soapData.getBytes(encoding);
            InputStream is = new ByteArrayInputStream(b, 0, b.length);
            
            
            RequestEntity re = new InputStreamRequestEntity(is);
            request.setRequestEntity(re);
            return executeMethod(request);
        } else if (postData != null) {
            PostMethod request = new PostMethod(url);
            // 增加cookie内容的容错处理(兼容性)。
            request.getParams().setParameter("http.protocol.cookie-policy", CookiePolicy.BROWSER_COMPATIBILITY);
            
            if (headers != null) {
                for (int i = 0; i < headers.length; i++) {
                    request.setRequestHeader(headers[i]);
                }
            }

            NameValuePair[] params = buildNameValuePairs();
            request.setRequestBody(params);
            return executeMethod(request);
        }
        //GET
        else {
            GetMethod request = new GetMethod(url);
            // 增加cookie内容的容错处理(兼容性)。
            request.getParams().setParameter("http.protocol.cookie-policy", CookiePolicy.BROWSER_COMPATIBILITY);
            if (headers != null) {
                for (int i = 0; i < headers.length; i++) {
                    request.setRequestHeader(headers[i]);
                }
            }
            return executeMethod(request);
        }
    }

    private NameValuePair[] buildNameValuePairs() {
        Set entrySet = postData.entrySet();
        int dataLength = entrySet.size();
        NameValuePair[] params = new NameValuePair[dataLength];
        int i = 0;
        for (Iterator itor = entrySet.iterator(); itor.hasNext();) {
            Map.Entry entry = (Map.Entry) itor.next();
            params[i++] = new NameValuePair(entry.getKey().toString(), entry.getValue().toString());
        }
        return params;
    }

    private Header[] buildHeaders() {
        //头部请求信息
        Header[] headers = null;
        if (header != null) {
            Set entrySet = header.entrySet();
            headers = new Header[entrySet.size()];
            int i = 0;
            for (Iterator itor = entrySet.iterator(); itor.hasNext();) {
                Map.Entry entry = (Map.Entry) itor.next();
                headers[i++] = new Header(entry.getKey().toString(), entry.getValue().toString());
            }
        }
        return headers;
    }

    private String executeMethod(HttpMethod request) throws Exception {
        String responseContent = null;
        InputStream responseStream = null;
        BufferedReader rd = null;
        try {
            httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(CONNECT_TIMEOUT);
            httpClient.executeMethod(request);
            
            //TODO 应该单独处理,代码有点长了
            if (encoding != null) {
                responseStream = request.getResponseBodyAsStream();
                rd = new BufferedReader(new InputStreamReader(responseStream, encoding));
                String tempLine = rd.readLine();
                StringBuffer tempStr = new StringBuffer();

                while (tempLine != null) {
                    tempStr.append(tempLine);
                    tempStr.append(CRLF);
                    tempLine = rd.readLine();
                }
                responseContent = tempStr.toString();
            } else {
                responseContent = request.getResponseBodyAsString();
            }
            LOG.debug("响应状态行: {}", request.getStatusLine());
            LOG.debug("响应头部:");
            for(Header hd : request.getResponseHeaders())
            {
                LOG.debug("  {}:{}", hd.getName(), hd.getValue());
            }
            
            Header locationHeader = request.getResponseHeader("location");
            //返回代码为302,301时，表示页面己经重定向，则重新请求location的url，这在一些登录授权取cookie时很重要
            if (locationHeader != null) {
                String redirectUrl = locationHeader.getValue();
                //TODO this.doRequest(redirectUrl, null, null, null);
            }
        } finally {
            IOUtils.closeQuietly(rd);
            IOUtils.closeQuietly(responseStream);
            request.releaseConnection();
        }
        return responseContent;
    }

    public void setPostData(Map<String, String> postData) {
        this.postData = postData;
    }

    public void setHeader(Map<String, String> header) {
        this.header = header;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public void setSoapData(String soapData) {
        this.soapData = soapData;
    }
}
